﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Red.Controls.ViewModels;

namespace Red.Controls.DataDriven
{
    /// <summary>
    /// A custom converter that obtains a value of data item's child with given name
    /// </summary>
    public sealed class CollectionItemsConverter : IValueConverter
    {
        private string _columnHeader;

        #region IValueConverter implementation

        public CollectionItemsConverter( string columnHeader )
        {
            _columnHeader = columnHeader;
        }

        public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
        {
            DataItem di = value as DataItem;

            DataItem valueItem = di?.Children.FirstOrDefault( el => el.Title == _columnHeader );
            if ( valueItem != null )
            {
                if ( valueItem.Kind != DataItemKind.Container )
                {
                    return valueItem.Value;
                }

                string res = string.Empty;
                foreach ( var child in valueItem.Children )
                {
                    if ( child != valueItem.Children.First() )
                    {
                        res += ", ";
                    }
                    res += child.Value;
                }
                return res;
            }

            return string.Empty;
        }

        public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
        {
            throw new NotImplementedException();
        }
        #endregion IValueConverter implementation
    }

    /// <summary>
    /// A control for displaying data in a table
    /// </summary>
    [InteropControl( "DataTable" )]
    public partial class DataTable : UserControl
    {
        #region Data

        private DataItem _rowsItem;

        #endregion Data

        #region Properties

        public DataItem Rows
        {
            get
            {
                return _rowsItem;
            }
        }

        #endregion Properties

        #region C-tor

        public DataTable()
        {
            DataContextChanged += DataTable_DataContextChanged;
            InitializeComponent();
        }

        #endregion C-tor

        #region Event handlers

        private async void DataTable_DataContextChanged( object sender, DependencyPropertyChangedEventArgs e )
        {
            DataItem oldDC = e.OldValue as DataItem;
            if ( oldDC != null )
            {
                DataItem headersArray = await oldDC.DigUpSubItemAsync( "_headers" );
                headersArray.Children.CollectionChanged -= Headers_CollectionChanged;

                _rowsItem.Children.CollectionChanged -= Rows_CollectionChanged;
            }

            DataItem newDC = e.NewValue as DataItem;
            if ( newDC != null )
            {
                DataItem headersArray = await newDC.DigUpSubItemAsync( "_headers" );
                headersArray.Children.CollectionChanged += Headers_CollectionChanged;
                await headersArray.RebuildAsync();

                _rowsItem = await newDC.DigUpSubItemAsync( "_rows" );
                _list.SetBinding( ListView.ItemsSourceProperty,
                    new Binding( "Rows.Children" )
                    {
                        Source = this
                    } );

                _rowsItem.Children.CollectionChanged += Rows_CollectionChanged;
                await _rowsItem.RebuildAsync( true );
            }
        }

        private void Rows_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
        {
            ObservableCollection<DataItem> coll = (ObservableCollection<DataItem>)sender;
            if ( coll.Count != 0 )
            {
                foreach ( var item in coll )
                {
                    DataItem rowItem = item as DataItem;
                    rowItem.Children.CollectionChanged += RowChildren_CollectionChanged;
                    rowItem.Children.CollectionChanged += Rows_CollectionChanged;
                    rowItem.IsExpanded = true;
                }
            }
        }

        private void RowChildren_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
        {
            _list.Items.Refresh();
        }

        private void Headers_CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
        {
            GridView gridView = _list.View as GridView;
            if ( gridView != null )
            {
                ObservableCollection<DataItem> coll = (ObservableCollection<DataItem>)sender;
                if ( coll.Count == 0 )
                {
                    gridView.Columns.Clear();
                }
                else
                { 
                    foreach ( var newItem in coll )
                    {
                        DataItem headerItem = newItem as DataItem;

                        GridViewColumn gvc = new GridViewColumn();
                        gvc.Header = headerItem.Value;
                        gvc.DisplayMemberBinding = new Binding()
                        {
                            Converter = new CollectionItemsConverter( headerItem.Value )
                        };
                        gridView.Columns.Add( gvc );
                    }
                }
            }
        }

        #endregion Event handlers
    }
}
